import bgyl from '@/assets/diagnostic/bgyl.png';
import bxyl from '@/assets/diagnostic/bxyl.png';
import nBgyl from '@/assets/diagnostic/n_bgyl.png';
import nBxyl from '@/assets/diagnostic/n_bxyl.png';
import nZdfx from '@/assets/diagnostic/n_zdfx.png';
import nZdsh from '@/assets/diagnostic/n_zdsh.png';
import zdfx from '@/assets/diagnostic/zdfx.png';
import zdsh from '@/assets/diagnostic/zdsh.png';

import ReportEditor from '@/pages/study/report-editor';
import AnalysisOverlay from '@/pages/study/report-editor/AnalysisOverlay';
import {
  AfterDiagnosisOrAudit,
  EcgXWave,
  NextStudyAfterHandle,
  PreviewReprot,
  RawEcgParam,
  VerticalLine,
  type DetailResult,
} from '@/pages/types/type';
import { checkAuthorize } from '@/utils/authorize';
import { Content, Page } from '@alita/flow';
import {
  setPageNavBar,
  useLocation,
  useNavigate,
  useSearchParams,
} from 'alita';
import { Button, DotLoading, Modal, Tabs, Toast } from 'antd-mobile';
import { DownOutline, UnorderedListOutline, UpOutline } from 'antd-mobile-icons';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn'; // 导入本地化语言
import relativeTime from 'dayjs/plugin/relativeTime';
import styles from './index.less';

dayjs.extend(relativeTime);
dayjs.locale('zh-cn');

import React, {
  Dispatch,
  SetStateAction,
  useEffect,
  useRef,
  useState,
  useCallback
} from 'react';

import { UseAuthModel } from '@/models/useAuthModel';
import { type EcgData, type PrintParam, type Study } from '@/pages/types/type';
import { decodeWaveFromHexStr } from '@/utils/ecgdata';
import {
  getRequestInit,
  obsPrifix,
  postRequestInit,
  urlPrefix,
} from '@/utils/http';
import { useModel } from 'alita';
import { ModalShowHandler } from 'antd-mobile/es/components/modal';
import { ToastHandler } from 'antd-mobile/es/components/toast';
import './index.less';
const numberFormator = new Intl.NumberFormat();

declare type ZoomLevel = {
  index: number;
  step: number;
  text: string;
  speeds: number[];
  gains: number[];
};
declare type SpeedItem = {
  index: number;
  image: string;
  text: string;
};

const BackgroundGrid = ({
  wave,
  ecgData,
  setActiveKey,
  onPrintParaChange,
}: {
  wave: EcgXWave;
  ecgData: EcgData;
  setActiveKey: (key: string) => void;
  onPrintParaChange: Dispatch<SetStateAction<PrintParam>>;
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const rulerRef = useRef<HTMLCanvasElement>(null);

  const [zoomLevel, setZoomLevel] = useState<number>(1);
  const [speedIndex, setSpeedIndex] = useState<number>(2);
  const [gainIndex, setGainIndex] = useState<number>(1);
  //const [mode, setMode] = useState<number>(0);
  // 当前页，用于绘图
  //const [pageIndex, setPageIndex] = useState<number>(0);
  // 控制面板展开/收缩状态
  const [panelExpanded, setPanelExpanded] = useState<boolean>(false);
  // 控制测量工具的显示隐藏状态，默认隐藏
  const [rulerVisible, setRulerVisible] = useState<boolean>(false);

  // 记录垂直位置移动量
  const [verticalMoves, setVerticalMoves] = useState<number[]>([]);
  const [horizontalMoves, setHorizontalMoves] = useState<number[]>([]);

  // 波形图拖动相关状态
  const [isDragging, setIsDragging] = useState<boolean>(false);
  const [dragStartX, setDragStartX] = useState<number>(0);
  const [dragStartY, setDragStartY] = useState<number>(0);

  //控制面板 显示 隐藏
  const [isVisible, setIsVisible] = useState<boolean>(false);
  const speedItems: SpeedItem[] = [
    {
      index: 0,
      text: '6.25mm/s',
      image: '/assets/options/wave_speed_125.png',
    },

    {
      index: 1,
      text: '12.5mm/s',
      image: '/assets/options/wave_speed_25.png',
    },
    {
      index: 2,
      text: '25mm/s',
      image: '/assets/options/wave_speed_50.png',
    },
    {
      index: 3,
      text: '50mm/s',
      image: '/assets/options/wave_speed_100.png',
    },
  ];

  const zoomLevels: ZoomLevel[] = [
    {
      index: 0,
      step: 2.5,
      text: '50%',
      speeds: [32, 16, 8, 4],
      gains: [16, 8, 4],
    },
    {
      index: 1,
      step: 5,
      text: '100%',
      speeds: [16, 8, 4, 2],
      gains: [8, 4, 2],
    },
    {
      index: 2,
      step: 10,
      text: '200%',
      speeds: [8, 4, 2, 1],
      gains: [4, 2, 1],
    },
  ];

  const stepX = zoomLevels[zoomLevel].speeds[speedIndex];
  const stepY = zoomLevels[zoomLevel].gains[gainIndex];

  useEffect(() => {
    var tHs = horizontalMoves.reduce((a, b) => a + b, 0);
    onPrintParaChange({
      zoomLevel,
      dataOffset: -Math.ceil(tHs * stepX),
      speedIndex,
      gainIndex,
      horizontalTranslate: Math.ceil(tHs),
      verticalTranslate: Math.ceil(verticalMoves.reduce((a, b) => a + b, 0)),
      devicePixelRatio: window.devicePixelRatio,
    });
  }, [zoomLevel, speedIndex, gainIndex, verticalMoves, horizontalMoves]);

  type RulerRect = {
    //path: Path2D | null,
    x: number;
    y: number;
    width: number;
    height: number;
    fillColor: string; // 'rgba(74, 144, 226, 0.7)',
    strokeColor: string; // '#1a73e8',
    handleSize: number;
    isDragging: boolean;
    activeHandle: string | null;
    startX: number;
    startY: number;
    origin: { x: number; y: number; width: number; height: number };
  };

  const [rulerReact, setRulerReact] = useState<RulerRect>({
    //path: new Path2D(),
    x: (window.innerWidth - window.innerWidth / 3) / 2, // 居中显示
    y: 150,
    width: window.innerWidth / 3, // 屏幕宽度的三分之一
    height: 200, // 固定200px高度
    fillColor: 'rgba(74, 144, 226, 0.7)',
    strokeColor: '#1a73e8',
    handleSize: 12,
    isDragging: false,
    activeHandle: null,
    startX: 0,
    startY: 0,
    origin: {
      x: (window.innerWidth - window.innerWidth / 3) / 2,
      y: 150,
      width: window.innerWidth / 3,
      height: 200,
    },
  });

  // 检查是否点击了控制点
  const checkHandleHit = (
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
  ) => {
    const { width, height, x: ruleX, y: ruleY } = rulerReact;
    const h = rulerReact.handleSize * 1.5; // 扩大点击区域
    const midX = ruleX + width / 2;
    const midY = ruleY + height / 2;

    // 检查顶部控制点
    if (x > midX - h && x < midX + h && y > ruleY - h && y < ruleY + h) {
      return 'top';
    }
    // 检查右侧控制点
    if (
      x > ruleX + width - h &&
      x < ruleX + width + h &&
      y > midY - h &&
      y < midY + h
    ) {
      return 'right';
    }
    // 检查底部控制点
    if (
      x > midX - h &&
      x < midX + h &&
      y > ruleY + height - h &&
      y < ruleY + height + h
    ) {
      return 'bottom';
    }
    // 检查左侧控制点
    if (x > ruleX - h && x < ruleX + h && y > midY - h && y < midY + h) {
      return 'left';
    }

    if (x >= ruleX && x <= ruleX + width && y >= ruleY && y <= ruleY + height) {
      return 'move';
    }

    return null;
  };

  // 窗口大小改变时强制重新渲染的状态
  const [windowSize, setWindowSize] = useState({
    width: window.innerWidth,
    height: window.innerHeight,
  });

  // 监听窗口大小改变
  useEffect(() => {
    const handleResize = () => {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });

      // 同时更新rulerReact的位置和尺寸以保持居中和正确比例
      setRulerReact((prev) => ({
        ...prev,
        x: (window.innerWidth - window.innerWidth / 3) / 2,
        width: window.innerWidth / 3,
        origin: {
          ...prev.origin,
          x: (window.innerWidth - window.innerWidth / 3) / 2,
          width: window.innerWidth / 3,
        },
      }));
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  useEffect(() => {
    const canvas = rulerRef.current;
    const ctx = canvas?.getContext('2d');
    if (ctx && canvas) {
      const devicePixelRatio = window.devicePixelRatio || 1;
      const displayWidth = windowSize.width;
      const displayHeight = windowSize.height - 46;

      // 设置canvas的实际像素尺寸
      canvas.width = displayWidth * devicePixelRatio;
      canvas.height = displayHeight * devicePixelRatio;

      // 设置canvas的显示尺寸
      canvas.style.width = displayWidth + 'px';
      canvas.style.height = displayHeight + 'px';

      // 缩放绘图上下文以匹配设备像素比
      ctx.scale(devicePixelRatio, devicePixelRatio);

      // 优化渲染质量，提高清晰度
      ctx.imageSmoothingEnabled = false;
      ctx.textRendering = 'optimizeSpeed';
    }
  }, [windowSize]);

  // 统一的开始事件处理函数（兼容鼠标和触摸）
  const handlePointerDown = (
    e:
      | React.MouseEvent<HTMLCanvasElement>
      | React.TouchEvent<HTMLCanvasElement>,
  ) => {
    const canvas = rulerRef.current;
    const ctx = canvas?.getContext('2d');
    if (!(canvas && ctx)) {
      return;
    }

    const rectPos = canvas.getBoundingClientRect();
    let clientX: number, clientY: number;

    // 根据事件类型获取坐标
    if ('touches' in e) {
      // 触摸事件
      const touch = e.touches[0];
      clientX = touch.clientX;
      clientY = touch.clientY;
    } else {
      // 鼠标事件
      clientX = e.clientX;
      clientY = e.clientY;
    }

    const pointerX = clientX - rectPos.left;
    const pointerY = clientY - rectPos.top;

    const hit: string | null = checkHandleHit(ctx, pointerX, pointerY);
    console.log(`hit=${hit}`);
    if (hit) {
      setRulerReact((pre) => ({
        ...pre,
        isDragging: true,
        activeHandle: hit,
        startX: pointerX,
        startY: pointerY,
        origin: { x: pre.x, y: pre.y, width: pre.width, height: pre.height },
      }));
    }
  }; // end handlePointerDown;

  // 鼠标悬停事件处理函数，用于改变鼠标样式
  const handleMouseHover = (e: React.MouseEvent<HTMLCanvasElement>) => {
    const canvas = rulerRef.current;
    const ctx = canvas?.getContext('2d');
    if (!(canvas && ctx)) {
      return;
    }

    const { isDragging } = rulerReact;

    // 如果正在拖拽，不改变鼠标样式
    if (isDragging) return;

    const rectPos = canvas.getBoundingClientRect();
    const pointerX = e.clientX - rectPos.left;
    const pointerY = e.clientY - rectPos.top;

    const hit: string | null = checkHandleHit(ctx, pointerX, pointerY);

    // 根据悬停的句柄类型设置不同的鼠标样式
    switch (hit) {
      case 'top':
      case 'bottom':
        canvas.style.cursor = 'ns-resize'; // 垂直调整大小
        break;
      case 'left':
      case 'right':
        canvas.style.cursor = 'ew-resize'; // 水平调整大小
        break;
      case 'move':
        canvas.style.cursor = 'move'; // 移动
        break;
      default:
        canvas.style.cursor = 'default'; // 默认鼠标样式
        break;
    }
  };

  // 统一的移动事件处理函数（兼容鼠标和触摸）
  const handlePointerMove = (
    e:
      | React.MouseEvent<HTMLCanvasElement>
      | React.TouchEvent<HTMLCanvasElement>,
  ) => {
    const canvas = rulerRef.current;
    const ctx = canvas?.getContext('2d');
    if (!(canvas && ctx)) {
      return;
    }

    const {
      isDragging,
      startX,
      startY,
      activeHandle,
      width,
      height,
      x,
      y,
      origin,
    } = rulerReact;

    // 如果不是触摸事件且没有拖拽，处理鼠标悬停样式
    if (!('touches' in e) && !isDragging) {
      handleMouseHover(e as React.MouseEvent<HTMLCanvasElement>);
      return;
    }

    if (!isDragging) return;

    const rectPos = canvas.getBoundingClientRect();
    let clientX: number, clientY: number;

    // 根据事件类型获取坐标
    if ('touches' in e) {
      // 触摸事件
      const touch = e.touches[0];
      clientX = touch.clientX;
      clientY = touch.clientY;
    } else {
      // 鼠标事件
      clientX = e.clientX;
      clientY = e.clientY;
    }

    const pointerX = clientX - rectPos.left;
    const pointerY = clientY - rectPos.top;

    const dx = pointerX - startX;
    const dy = pointerY - startY;

    switch (activeHandle) {
      case 'move':
        setRulerReact((pre) => ({
          ...pre,
          x: origin.x + dx,
          y: origin.y + dy,
        }));
        break;
      case 'top':
        setRulerReact((pre) => ({
          ...pre,
          y: origin.y + dy,
          height: origin.height - dy,
        }));
        break;
      case 'right':
        setRulerReact((pre) => ({ ...pre, width: origin.width + dx }));
        break;
      case 'bottom':
        setRulerReact((pre) => ({ ...pre, height: origin.height + dy }));
        break;
      case 'left':
        setRulerReact((pre) => ({
          ...pre,
          x: origin.x + dx,
          width: origin.width - dx,
        }));
        break;
    } // end switch
  }; // end handlePointerMove

  // 鼠标离开canvas时重置鼠标样式
  const handleMouseLeave = () => {
    const canvas = rulerRef.current;
    if (canvas) {
      canvas.style.cursor = 'default';
    }
  };

  // 统一的结束事件处理函数（兼容鼠标和触摸）
  const handlePointerUp = (
    e:
      | React.MouseEvent<HTMLCanvasElement>
      | React.TouchEvent<HTMLCanvasElement>,
  ) => {
    console.log(e);
    const canvas = rulerRef.current;
    if (canvas) {
      canvas.style.cursor = 'default'; // 拖拽结束时重置鼠标样式
    }

    setRulerReact((pre) => ({ ...pre, isDragging: false, activeHandle: null }));
  }; // end handlePointerUp

  // 波形图拖动事件处理函数
  const handleWavePointerDown = (
    e:
      | React.MouseEvent<HTMLCanvasElement>
      | React.TouchEvent<HTMLCanvasElement>,
  ) => {
    const canvas = canvasRef.current;
    if (!canvas) return;

    const rectPos = canvas.getBoundingClientRect();
    let clientX: number, clientY: number;

    // 根据事件类型获取坐标
    if ('touches' in e) {
      const touch = e.touches[0];
      clientX = touch.clientX;
      clientY = touch.clientY;
    } else {
      clientX = e.clientX;
      clientY = e.clientY;
    }

    const pointerX = clientX - rectPos.left;
    const pointerY = clientY - rectPos.top;

    setIsDragging(true);

    setDragStartX(pointerX);
    setDragStartY(pointerY);

    setVerticalMoves((pre) => [...pre, 0]); // B263
    setHorizontalMoves((pre) => [...pre, 0]); // B263
  };

  const handleWavePointerMove = (
    e:
      | React.MouseEvent<HTMLCanvasElement>
      | React.TouchEvent<HTMLCanvasElement>,
  ) => {
    if (!isDragging) return;

    const canvas = canvasRef.current;
    if (!canvas) return;

    const rectPos = canvas.getBoundingClientRect();
    let clientX: number, clientY: number;

    // 根据事件类型获取坐标
    if ('touches' in e) {
      const touch = e.touches[0];
      clientX = touch.clientX;
      clientY = touch.clientY;
    } else {
      clientX = e.clientX;
      clientY = e.clientY;
    }

    const pointerX = clientX - rectPos.left;
    const pointerY = clientY - rectPos.top;
    const deltaX = pointerX - dragStartX;
    const deltaY = pointerY - dragStartY;

    const hTotal = horizontalMoves.reduce(
      (a, b, index) => a + (index < horizontalMoves.length - 1 ? b : deltaX),
      0,
    );
    const vTotal = verticalMoves.reduce(
      (a, b, index) => a + (index < verticalMoves.length - 1 ? b : deltaY),
      0,
    );

    if (vTotal <= 100 && vTotal >= -800) {
      setVerticalMoves((pre) => {
        const v = [...pre];
        v[pre.length - 1] = deltaY;
        return v;
      });
    }

    const devicePixelRatio = window.devicePixelRatio || 1;

    const maxX = ecgData.dataLength / stepX; // * devicePixelRatio;

    const displayWidth = windowSize.width;
    //const displayHeight = windowSize.height - 46;

    console.log(`displayWidth=${displayWidth} , canvas.with=${canvas.width
      } ecgData.dataLength =${ecgData.dataLength
      },stepX=${stepX} maxX=${maxX} devicePixelRatio=${devicePixelRatio}  ,
      displayWidth * devicePixelRatio=${displayWidth * devicePixelRatio} `);
    console.log(
      `displayWidth * devicePixelRatio - maxX 相差 ${displayWidth * devicePixelRatio - maxX
      }, hTotal=${hTotal}, hTotal / devicePixelRatio=${hTotal / devicePixelRatio
      } `,
    );

    console.log(
      `复制=displayWidth * devicePixelRatio * stepX=${displayWidth * devicePixelRatio * stepX
      } , -maxX=${displayWidth * devicePixelRatio * stepX - ecgData.dataLength
      }  `,
    );
    // var p6 =
    //   (displayWidth * devicePixelRatio * stepX - ecgData.dataLength) /
    //   window.devicePixelRatio;
    const p6 = Math.min(0, displayWidth - ecgData.dataLength / stepX);
    console.log(`p6=${p6}`);

    if (hTotal < 0 && hTotal > (p6-50)) {
      setHorizontalMoves((pre) => {
        const v = [...pre];
        v[pre.length - 1] = deltaX;
        return v;
      });
    }

  };

  const handleWavePointerUp = (
    e:
      | React.MouseEvent<HTMLCanvasElement>
      | React.TouchEvent<HTMLCanvasElement>,
  ) => {
    console.log(e);
    setIsDragging(false);
    setDragStartX(0);
  };

  interface OffsetXY {
    offsetX: number;
    offsetY: number;
}
  const [mouseXYOnCanvas, setMouseXYOnCanvas] = useState<OffsetXY>()
  // canvas 的mouse move事件
  const handleMouseMoveOnCanvas = useCallback((event: MouseEvent) => {
    const { offsetX, offsetY } = event;
    setMouseXYOnCanvas({ offsetX, offsetY })
    console.log('handleMouseMoveOnCanvas:', event.offsetX, event.offsetY, window.devicePixelRatio);
  }, []);

  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas?.getContext('2d');
    if (ctx && canvas) {
      // 添加监听，泛型参数为"mousemove"
      canvas.addEventListener<"mousemove">("mousemove", handleMouseMoveOnCanvas);
      return () => {
        // 移除时需保持相同类型和引用
        canvas.removeEventListener<"mousemove">("mousemove", handleMouseMoveOnCanvas);
      };
    }
  }, [handleMouseMoveOnCanvas]);

  function drawDiamond(
    ctx: CanvasRenderingContext2D,
    x: number,
    y: number,
    size: number,
  ) {
    ctx.fillStyle = '#88a1e5ff';
    ctx.beginPath();
    ctx.moveTo(x, y - size);
    ctx.lineTo(x + size, y);
    ctx.lineTo(x, y + size);
    ctx.lineTo(x - size, y);
    ctx.closePath();
    ctx.fill();
  }

  function drawResizeHandles(ctx: CanvasRenderingContext2D) {
    const h = rulerReact.handleSize;
    const midX = rulerReact.x + rulerReact.width / 2;
    const midY = rulerReact.y + rulerReact.height / 2;

    // 控制点直接置于矩形边中点
    drawDiamond(ctx, midX, rulerReact.y, h); // 顶部
    drawDiamond(ctx, rulerReact.x + rulerReact.width, midY, h); // 右侧
    drawDiamond(ctx, midX, rulerReact.y + rulerReact.height, h); // 底部
    drawDiamond(ctx, rulerReact.x, midY, h); // 左侧
  }

  const toGoodLine = (cur: number, step: number): number => {
    return cur;
    // const mlx = cur % step == 0 ? cur : parseFloat((cur + (step - (cur % step))).toFixed(10));
    // console.log(`cur=${cur},stpe=${step}, mlx=${mlx} `);
    // return mlx;
    // return 0;
  };

  //  rulerReact 发生变更
  useEffect(() => {
    const canvas: HTMLCanvasElement | null = rulerRef.current;
    const ctx = canvas?.getContext('2d');
    if (ctx && canvas) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 绘制填充矩形
      ctx.fillStyle = rulerReact.fillColor;
      const path1 = new Path2D();
      const { x, y, width, height } = rulerReact;
      path1.rect(x, y, width, height);

      // 绘制边框
      ctx.strokeStyle = rulerReact.strokeColor;
      ctx.lineWidth = 1;
      ctx.fill(path1);

      let path = new Path2D();
      let i = -1;
      while (true) {
        ++i;
        let t1 = x - i * width;
        if (t1 >= 0) {
          path.moveTo(t1, 0);
          path.lineTo(t1, canvas.height);
        } else {
          break;
        }
      }
      i = 0;
      while (true) {
        ++i;
        let t1 = x + i * width;
        if (t1 >= 0 && t1 <= canvas.width) {
          path.moveTo(t1, 0);
          path.lineTo(t1, canvas.height);
        } else {
          break;
        }
      }
      ctx.stroke(path);

      // 测量结果的文本区域
      // let p000 = new Path2D(`M${x} ${y} h ${width} v -20 h -${width} Z`);
      // ctx.fill(p000);
      ctx.fillStyle = 'rgba(130, 138, 41, 0.5)';
      let nameB = new Path2D();
      nameB.rect(x, y - 50, width, 40);
      ctx.fill(nameB);

      drawResizeHandles(ctx);
    } // end if ctx && canvas
  }, [rulerReact]);

  // 画导联图，拆线图
  useEffect(() => {
    const canvas = canvasRef.current;
    const ctx = canvas?.getContext('2d');

    if (ctx && canvas && canvas !== null) {
      // 获取设备像素比，解决高DPI显示器模糊问题
      const drp = window.devicePixelRatio || 1;
      const displayWidth = windowSize.width;
      const displayHeight = windowSize.height - 46;

      // 设置canvas的实际像素尺寸
      canvas.width = displayWidth * drp;
      canvas.height = displayHeight * drp;

      // 设置canvas的显示尺寸
      canvas.style.width = displayWidth + 'px';
      canvas.style.height = displayHeight + 'px';

      // 缩放绘图上下文以匹配设备像素比
      ctx.scale(drp, drp);

      // 优化渲染质量，提高清晰度
      ctx.imageSmoothingEnabled = false;
      ctx.textRendering = 'optimizeSpeed';

      // 清除画布
      ctx.clearRect(0, 0, displayWidth, displayHeight);
      // 根据设备像素比和设备类型调整线宽
      const isMobileScreen =
        /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
          navigator.userAgent,
        );
      const baseLineWidth = isMobileScreen ? 0.3 : 0.3;
      ctx.lineWidth = baseLineWidth * Math.min(devicePixelRatio, 2);

      // 启用像素对齐，减少模糊
      ctx.translate(0.5, 0.5);
      const piexPerMM = zoomLevels[zoomLevel].step;
      let mm = piexPerMM;

      //ctx.strokeStyle = '#ffe1e1';
      const gridCanvasWidth = windowSize.width;
      const gridCanvasHeight = windowSize.height;
      const grdiPath1 = new Path2D();
      for (let i = 0; i < gridCanvasWidth / mm; i++) {
        grdiPath1.moveTo(i * mm, 0);
        grdiPath1.lineTo(i * mm, gridCanvasHeight);
      }

      for (let i = 0; i < gridCanvasHeight / mm; i++) {
        grdiPath1.moveTo(0, i * mm);
        grdiPath1.lineTo(gridCanvasWidth, i * mm);
      }

      mm = piexPerMM * 5;
      //ctx.beginPath();
      //ctx.strokeStyle = '#ffc8c8';
      const grdiPath2 = new Path2D();
      for (let i = 0; i < gridCanvasWidth / mm; i++) {
        grdiPath2.moveTo(i * mm, 0);
        grdiPath2.lineTo(i * mm, gridCanvasHeight);
      }

      for (let i = 0; i < gridCanvasHeight / mm; i++) {
        grdiPath2.moveTo(0, i * mm);
        grdiPath2.lineTo(gridCanvasWidth, i * mm);
      }

      ctx.strokeStyle = '#fae6E6';
      ctx.stroke(grdiPath1);
      ctx.strokeStyle = '#ffaeae';
      ctx.stroke(grdiPath2);
      ctx.restore();

      // 每一页上拆线数
      // const pageLeadCount = Math.ceil(
      //   ecgData.leadCount / modeItems[mode].pageSize,
      // );

      // 设置波形线宽，根据设备像素比和设备类型调整
      const isMobile =
        /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
          navigator.userAgent,
        );
      const baseWaveLineWidth = isMobile ? 0.5 : 0.5;

      ctx.lineWidth = baseWaveLineWidth * Math.min(devicePixelRatio, 2);
      ctx.strokeStyle = '#0000ff';

      // 确保像素对齐，提高清晰度
      ctx.save();

      const waveCanvasWidth = windowSize.width;
      const waveCanvasHeight = windowSize.height;
      //const blockHeight = waveCanvasHeight / pageLeadCount;

      // 校准偏移量
      const calibration = 10;
      // 取得，取得，每个导联的最大值，最少值，高度
      const { data, leadNames } = ecgData;
      const vhs = leadNames.map((ln) => {
        const rawValues = data[ln] as number[];
        const minV = Math.min(...rawValues);
        const maxV = Math.max(200, Math.max(...rawValues));
        if (maxV > 0 !== minV > 0) {
        }
        return {
          vh: minV >= 0 ? maxV : maxV - minV,
          minV,
          maxV,
        };
      });
      const hLines = new Path2D();
      // 导联线了
      const leadLines = new Path2D();

      const gainScale = stepY;
      const vTsRaw = verticalMoves.reduce((a, b) => a + b, 0);
      const vTs = !isDragging ? toGoodLine(vTsRaw, 25) : vTsRaw; // verticalMoves.reduce((a, b) => a + b, 0);
      const hTs = horizontalMoves.reduce((a, b) => a + b, 0);
      ctx.save();

      ctx.translate(hTs + calibration, vTs);
      const vspace = 40;
      // 产生一个数据组。
      Array.from(
        { length: leadNames.length /* 3 */ },
        (_, itx) => itx /** 0 1 2 */,
      ).forEach((j, leadIndex) => {
        const rawValues = data[leadNames[j]] as number[];
        const leadName = leadNames[j];
        const vOffset = vhs.reduce(
          (total, { vh, maxV }, px3) =>
            total + (px3 < j ? vh : (px3 === j ? maxV : 0)),
          0,
        );

        const vOffSet2 = vOffset / gainScale;

        const ppt = !isDragging
          ? toGoodLine(vspace + vOffSet2, 25)
          : vspace + vOffSet2;

        
        console.log(
          `${leadName}, [${Math.min(...rawValues)},${Math.max(
            ...rawValues,
          )}] [${Math.min(...rawValues) / stepY},${Math.max(...rawValues) / stepY
          }]`,
        );

        // 接下来，水平方向，使用line to,在每个像素点上画出数据，由于数据
        // 肯定是比像素点多的，所以需要使用使用 stepX ，来隔点取样。
        // 当  stepX 越大时，在同一宽度上，绘制的波型越少，给到的观感是：走速快：
        // 当  stepX 越少时，在同一宽度上，组件的波型越多，组到的观感是：走速慢：
        //const qrsLine = new Path2D();
        rawValues.forEach((v: number, pIndex: number) => {
          if (pIndex % stepX === 0) {
            const y1 = v / stepY;
            const x1 = pIndex / stepX;
            const y2 = ppt - y1;
            if (pIndex === 0) {
              leadLines.moveTo(x1, y2);
            } else {
              leadLines.lineTo(x1, y2);
            }
            // const dropInQrsIndex = wave.QRSList.findIndex(
            //   ({ SS, QQ }) => pIndex <= SS && pIndex >= QQ,
            // );
            
          }
        }); // end rawValues
        //qrsLines.addPath(qrsLine);

        //绘制定标、导联名称开始
        ctx.strokeStyle = '#9f7424a2';
        ctx.fillText(ecgData.leadNames[j], 25 - hTs, ppt - 12);
        ctx.beginPath();
        ctx.moveTo(0 - hTs, ppt);
        ctx.lineTo(5 - hTs, ppt);
        ctx.lineTo(5 - hTs, ppt - 200 / stepY);
        ctx.lineTo(15 - hTs, ppt - 200 / stepY);
        ctx.lineTo(15 - hTs, ppt);
        ctx.lineTo(20 - hTs, ppt);
        ctx.stroke();
      }); // end 每一个导联

      // 批量产生path2D对象
      const qrsRangePaths = Array.from(
        { length: wave.QRSList.length },
        (_, x_) => new Path2D(),
      );
      // 批量产生的距型区域
      const qrsRangeRects = Array.from(
        { length: wave.QRSList.length },
        (_, x_) => new Path2D(),
      );

      wave.QRSList.forEach(({ QQ, SS }, qrsIndex) => {
        //******************* */
        const qrsRangePath = new Path2D();
        let  firstX, lastX ,lastY,firstY  ;

        Array.from(
          { length: leadNames.length /* 3 */ },
          (_, itx) => itx /** 0 1 2 */,
        ).forEach((j) => {
          
          const rawValues = data[leadNames[j]] as number[];
          const vOffset = vhs.reduce(
            (total, { vh, maxV }, px3) =>
              total + (px3 < j ? vh : px3 === j ? maxV : 0),
            0,
          );
          const vOffSet2 = vOffset / gainScale;
          const ppt = !isDragging
            ? toGoodLine(vspace + vOffSet2, 25)
            : vspace + vOffSet2;

          let firstTouch = true;
  

          rawValues.forEach((v: number, pIndex: number) => {
            if (pIndex % stepX === 0) {
              const y1 = v / stepY;
              const x1 = pIndex / stepX;
              const y2 = ppt - y1;
              const inQrs = pIndex <= SS && pIndex >= QQ;
              if (inQrs) {
                if (firstTouch) {
                  qrsRangePath.moveTo(x1, y2);
                  firstY = y2;
                  firstX = x1;
                  firstTouch = false;
                } else {
                  qrsRangePath.lineTo(x1, y2);
                  lastX = x1;lastY = y2;
                }
              }
            }
          }); // end rawValues
        }); // end 每一个导联
        //******************* */
        qrsRangePaths[qrsIndex].addPath(qrsRangePath);
        const rangeRectPath = new Path2D();
        rangeRectPath.rect(firstX ||0, -vTs,(lastX || 0)  -(firstX || 0),  displayHeight  )
        // 构建矩形
        qrsRangeRects[qrsIndex].addPath( rangeRectPath );


      }); // end 每一个 QRSList

      ctx.strokeStyle = '#2264afff';
      ctx.stroke(hLines);
      ctx.strokeStyle = '#331490ff';
      ctx.stroke(leadLines);
      // 绘制QRS波
      ctx.strokeStyle = '#db2f74ff';
      // 根据不同的颜色绘制
       const {offsetX,offsetY} = mouseXYOnCanvas||{}
       const hxy  = offsetX !==undefined && offsetY !==undefined;

      wave.QRSList.forEach(({ type }, qrsIndex) => {
       
        var path2d = qrsRangePaths[qrsIndex];
        var reactPath2d =  qrsRangeRects[ qrsIndex]
        const color =  hxy && ctx.isPointInPath(reactPath2d, offsetX * drp,offsetY * drp )?'#0813e2ff':(type === 11 ? 'red' : type === 13 ? 'blue' : '#331490ff');
        //const color: string = type === 11 ? 'red' : type === 13 ? 'blue' : '#331490ff';
        ctx.strokeStyle = color;
        if( color ==='#0813e2ff'){
          //ctx.stroke( qrsRangeRects[ qrsIndex]);
        }
        
        ctx.stroke(path2d);
      });

      //const linGrad = ctx.createLinearGradient(0, 0, 0, 150);
      // const linGrad = ctx.createLinearGradient(-hTs - calibration, -vTs, waveCanvasWidth + (Math.abs(hTs)), 10);
      // linGrad.addColorStop(0, "#00ABEB");
      // linGrad.addColorStop(1, "#2a3b3dff");
      ctx.fillStyle = 'rgba(244, 246, 250,0.65)';//'#58d6b7ff';
      // 顶部矩形
      ctx.fillRect(
        -hTs - calibration,
        -vTs,
        waveCanvasWidth + Math.abs(hTs),
        30,
      );
      //ctx.fillStyle = '#4562adff';

      // 左上角矩形
      ctx.fillRect(-hTs - calibration, -vTs + 30, 40, 20);
      const leftTime = `${((-hTs - calibration) * stepX * 0.001).toFixed(1)}s`;
      const leftTimeMetrics = ctx.measureText(leftTime);
      // 绘制当前左边时间
      ctx.fillStyle = '#0b2d83ff';
      ctx.font = '14px serif';
      ctx.fillText(
        leftTime,
        -hTs - calibration + leftTimeMetrics.width / 2,
        -vTs + 45,
      );

      // 底部矩形
      //ctx.fillStyle = '#519786ff';
      ctx.fillStyle = 'rgba(244, 246, 250,0.65)';
      ctx.fillRect(
        -hTs - calibration,
        -vTs + waveCanvasHeight - 70,
        waveCanvasWidth + Math.abs(hTs),
        50,
      );
      const trianglePaths = new Path2D();
      const redTrianglePaths = new Path2D();
      const blueTrianglePaths = new Path2D();

      // 绘制三角形
      wave.QRSList.forEach((qrs, j) => {
        const qrs0 = qrs.TT;
        const type: number = qrs.type;
        const offsetX = qrs0 / stepX;
        if (type === 11) {
          redTrianglePaths.moveTo(offsetX + -5, 0 - vTs);
          redTrianglePaths.lineTo(offsetX + 5, 0 - vTs);
          redTrianglePaths.lineTo(offsetX + 0, 10 - vTs);
          redTrianglePaths.closePath();
        }
        if (type === 13) {
          //
          blueTrianglePaths.moveTo(offsetX + -5, 0 - vTs);
          blueTrianglePaths.lineTo(offsetX + 5, 0 - vTs);
          blueTrianglePaths.lineTo(offsetX + 0, 10 - vTs);
          blueTrianglePaths.closePath();
        } else {
          trianglePaths.moveTo(offsetX + -5, 0 - vTs);
          trianglePaths.lineTo(offsetX + 5, 0 - vTs);
          trianglePaths.lineTo(offsetX + 0, 10 - vTs);
          trianglePaths.closePath();
        }
        ctx.fillStyle = 'black';
        ctx.font = '12px serif';
        if (j < wave.QRSList.length - 1) {
          const qrs1 = wave.QRSList[j + 1].TT;
          const rr: string = `${qrs1 - qrs0}`;
          var hr = (60000 / (qrs1 - qrs0)).toFixed(1);
          const metrics = ctx.measureText(rr);
          const metricsHr = ctx.measureText(hr);

          ctx.fillText(
            rr,
            offsetX + ((qrs1 - qrs0) / stepX - metrics.width) / 2,
            10 - vTs,
          );
          ctx.fillText(
            hr,
            offsetX + ((qrs1 - qrs0) / stepX - metricsHr.width) / 2,
            25 - vTs,
          );
        }
      });
      ctx.fillStyle = 'black';
      ctx.fill(trianglePaths);
      ctx.fillStyle = 'red';
      ctx.fill(redTrianglePaths);
      ctx.fillStyle = 'blue';
      ctx.fill(blueTrianglePaths);

      // 绘制时间，在底部
      ctx.strokeStyle = '#000000';
      ctx.font = '12px serif';

      let totalSec = Math.floor(ecgData.dataLength / 1000);
      for (let i = 0; i < totalSec; i++) {
        let mm = Math.floor((i * 1000) / stepX);
        ctx.fillText(i + 's', mm - 5, waveCanvasHeight - 55 - vTs);
        ctx.moveTo(mm, waveCanvasHeight - vTs);
        ctx.lineTo(mm, waveCanvasHeight - 50 - vTs);
        ctx.stroke();
      }
      ctx.restore();

      // function getPointInPath(e: MouseEvent) {
      //   const rectPos = canvas?.getBoundingClientRect();
      //   const rect = canvas?.getBoundingClientRect();
      //   let clientX: number, clientY: number;

      //   // 根据事件类型获取坐标
      //   clientX = e.clientX;
      //   clientY = e.clientY;
      //   const pointerX = clientX - rectPos?.left!;
      //   const pointerY = clientY - rectPos?.top!;

      //   // 获取当前设备像素比
      //   const currentDevicePixelRatio = window.devicePixelRatio || 1;
      //   const dpr = window.devicePixelRatio || 1;

      //   // 确保使用与绘制时完全相同的hTs和vTs值
      //   const currentVTs = verticalMoves.reduce((a, b) => a + b, 0);
      //   const currentHTs = horizontalMoves.reduce((a, b) => a + b, 0);
      //   const currentCalibration = 10;

      //   // 修复坐标计算：正确处理设备像素比和Canvas缩放
      //   // 1. 将浏览器坐标转换为Canvas逻辑坐标
      //   const canvasLogicalX =
      //     ((e.clientX - rect.left) * (canvas.width / rect.width)) / dpr;
      //   const canvasLogicalY =
      //     ((e.clientY - rect.top) * (canvas.height / rect.height)) / dpr;

      //   // 2. 将Canvas逻辑坐标转换到变换后的坐标系（三角形绘制的坐标系）
      //   // 三角形是在ctx.translate(hTs + calibration, vTs)之后绘制的
      //   // 所以需要将点击坐标转换到这个变换后的坐标系
      //   const drawingX = canvasLogicalX - (currentHTs + currentCalibration);
      //   const drawingY = canvasLogicalY - currentVTs;

      //   // 3. 应用绘制时的变换状态进行isPointInPath检测
      //   ctx.save();
      //   ctx.scale(currentDevicePixelRatio, currentDevicePixelRatio);
      //   ctx.translate(0.5, 0.5);
      //   ctx.translate(currentHTs + currentCalibration, currentVTs);

      //   // 4. 在相同变换状态下进行检测，使用变换后的坐标
      //   const isInRedTriangle = ctx.isPointInPath(
      //     redTrianglePaths,
      //     drawingX,
      //     drawingY,
      //   );

      //   ctx.restore();

      //   // 手动计算变换后坐标（用于调试对比）
      //   const scaledX = pointerX / currentDevicePixelRatio;
      //   const scaledY = pointerY / currentDevicePixelRatio;
      //   // 应用与drawingX/drawingY相同的变换逻辑
      //   const transformedX = scaledX - (currentHTs + currentCalibration);
      //   const transformedY = scaledY - currentVTs;

      //   console.log(`点击坐标详情:`);
      //   console.log(`  设备像素比: ${currentDevicePixelRatio}`);
      //   console.log(`  浏览器坐标: (${e.clientX}, ${e.clientY})`);
      //   console.log(`  Canvas坐标: (${pointerX}, ${pointerY})`);
      //   console.log(`  Canvas逻辑坐标: (${canvasLogicalX}, ${canvasLogicalY})`);
      //   console.log(`  变换后坐标系坐标: (${drawingX}, ${drawingY})`);
      //   console.log(`  缩放后坐标: (${scaledX}, ${scaledY})`);
      //   console.log(`  变换前坐标: (${scaledX}, ${scaledY})`);
      //   console.log(`  最终变换后坐标: (${transformedX}, ${transformedY})`);
      //   console.log(
      //     `  变换偏移: hTs=${currentHTs}, vTs=${currentVTs}, calibration=${currentCalibration}`,
      //   );
      //   console.log(`  isPointInPath结果:`);
      //   console.log(`    ✓ 修复后的检测结果: ${isInRedTriangle}`);
      //   console.log(
      //     `    ✗ 旧方法检测结果: ${ctx?.isPointInPath(
      //       redTrianglePaths,
      //       pointerX,
      //       pointerY,
      //     )}`,
      //   );

      //   // 打印所有红色三角形的位置信息
      //   console.log(`红色三角形位置信息:`);
      //   wave.QRSList.forEach((qrs, j) => {
      //     const qrs0 = qrs.TT;
      //     const type = qrs.type;
      //     if (type === 11) {
      //       const offsetX = qrs0 / stepX;

      //       // 检查点击是否在这个三角形范围内（使用变换后的坐标系）
      //       // 三角形绘制时Y坐标使用了 (0 - vTs) 和 (10 - vTs)
      //       // 在Canvas变换后，实际的三角形Y坐标范围是：
      //       const triangleMinY = 0 - currentVTs;
      //       const triangleMaxY = 10 - currentVTs;
      //       const triangleX = offsetX;

      //       console.log(
      //         `  三角形${j}: 原始中心X=${offsetX}, 变换后中心X=${triangleX}, 范围X=[${triangleX - 5
      //         }, ${triangleX + 5}], 范围Y=[${triangleMinY}, ${triangleMaxY}]`,
      //       );

      //       const inXRange =
      //         drawingX >= triangleX - 5 && drawingX <= triangleX + 5;
      //       const inYRange =
      //         drawingY >= triangleMinY && drawingY <= triangleMaxY;
      //       console.log(
      //         `    手动计算范围检测: X=${inXRange}, Y=${inYRange}, 总体=${inXRange && inYRange
      //         }`,
      //       );
      //       console.log(
      //         `    变换后坐标系检测: drawingX=${drawingX}, 三角形范围X=[${triangleX - 5
      //         }, ${triangleX + 5}]`,
      //       );
      //     }
      //   });
      //   // 如果检测到点击在红色三角形内，可以在这里添加相应的处理逻辑
      //   if (isInRedTriangle) {
      //     console.log('✅ 成功检测到红色三角形点击！');
      //     // 在这里添加你的业务逻辑
      //   }
      // }
      // canvas.removeEventListener('dblclick', getPointInPath);
      // canvas.addEventListener('dblclick', getPointInPath);

    } // end if ctx
  }, 
  [
    zoomLevel,
    speedIndex,
    gainIndex,
    ecgData,
    windowSize,
    verticalMoves,
    horizontalMoves,
    isDragging,
    mouseXYOnCanvas
  ]);
  // 画导联图，拆线图结束

  return (
    <div style={{ position: 'relative' }}>
      <canvas
        ref={canvasRef}
        id="canvasContainer"
        style={{ position: 'absolute', zIndex: 1, cursor:'crosshair' }}
        onMouseDown={handleWavePointerDown}
        onMouseMove={handleWavePointerMove}
        onMouseUp={handleWavePointerUp}
        onMouseLeave={handleWavePointerUp}
        onTouchStart={handleWavePointerDown}
        onTouchMove={handleWavePointerMove}
        onTouchEnd={handleWavePointerUp}
      ></canvas>
      <canvas
        ref={rulerRef}
        id="ruler"
        style={{
          zIndex: 2,
          position: 'absolute',
          display: rulerVisible ? 'block' : 'none',
        }}
        onMouseDown={handlePointerDown}
        onMouseMove={handlePointerMove}
        onMouseUp={handlePointerUp}
        onMouseLeave={handleMouseLeave}
        onTouchStart={handlePointerDown}
        onTouchMove={handlePointerMove}
        onTouchEnd={handlePointerUp}
      ></canvas>

      {/* 简化的固定按钮组 - 保持原有Fab样式 */}
      <div className="diagnostic-button-group">
        {isVisible && (
          <div>
            <button
              type="button"
              onClick={() => setZoomLevel((prev) => (prev + 1) % 3)}
              className="diagnostic-button"
            >
              <img src={require('@/assets/options/wave_zoom.png')} />
              <span>缩放</span>
            </button>

            <button
              type="button"
              onClick={() => setSpeedIndex((prev) => (prev + 1) % 4)}
              className="diagnostic-button"
            >
              <img
                src={require(`@/assets/options/${speedItems[speedIndex].image
                  .split('/')
                  .pop()}`)}
              />
              <span>走速</span>
            </button>
            <button
              type="button"
              onClick={() => setGainIndex((prev) => (prev + 1) % 3)}
              className="diagnostic-button"
            >
              <img
                src={require(`@/assets/options/wave_gain_${gainIndex === 0 ? '5' : gainIndex === 1 ? '10' : '20'
                  }.png`)}
              />
              <span>增益</span>
            </button>

            {/* <button
          type="button"
          onClick={() => setMode((prev) => (prev + 1) % 3)}
          className="diagnostic-button"
        >
          <img
            src={require(`@/assets/options/${modeItems[mode].image
              .split('/')
              .pop()}`)}
          />
          <span>模式</span>
        </button> */}

            <button
              type="button"
              onClick={() => setRulerVisible((prev) => !prev)}
              className="diagnostic-button"
            >
              <img src={require('@/assets/options/ruler-action.png')} />
              <span>测量</span>
            </button>

            <button
              type="button"
              onClick={() => setActiveKey('report')}
              className="diagnostic-button"
            >
              <img src={require('@/assets/options/details.png')} />
              <span>写报告</span>
            </button>

            <button
              type="button"
              onClick={() => setActiveKey('analysis')}
              className="diagnostic-button"
            >
              <img src={require('@/assets/options/details.png')} />
              <span>自动分析</span>
            </button>
          </div>
        )}
        <button
          type="button"
          onClick={() => setIsVisible(!isVisible)}
          className="diagnostic-button"
        >
          {isVisible ? <UpOutline /> : <DownOutline />}
        </button>
      </div>
    </div>
  );
};

export default () => {
  const navigate = useNavigate();
  const location = useLocation();
  const [searchParams, setSearchParams] = useSearchParams();
  const [tokening, setTokening] = useState<boolean>(true);
  const [tokenFail, setTokenFail] = useState<string | undefined>(undefined);
  const [authOK, setAuthOK] = useState<boolean>(false);
  const [loadFails, setLoadFails] = useState<string[]>([]);
  const [loadOK, setLoadOK] = useState<string | undefined>(undefined);
  const [loadingTimes, setLoadingTimes] = useState<number>(1);

  const [study, setStudy] = useState<Study>();

  const [ecgData, setEcgData] = useState<EcgData>();

  console.log(`searchParams.get('activeKey')=${searchParams.get('activeKey')}`);

  const [activeKey, setActiveKey] = useState<string>(
    searchParams.get('activeKey') || 'wave',
  );
  const [preKey, setPreKey] = useState<string>('wave');
  const [ecgParams, setEcgParams] = useState<RawEcgParam[]>([]);
  const [verticalLines, setVerticalLines] = useState<VerticalLine[]>([]);
  const [autoAnalysisResult, setAutoAnalysisResult] = useState<string>('');
  const [previewReportResult, setPreviewReportResult] =
    useState<PreviewReprot>();

  const [printParam, setPrintParam] = useState<PrintParam>({});

  const model: UseAuthModel = useModel('useAuthModel');

  useEffect(() => {
    setPageNavBar({
      pagePath: location.pathname,
      navBar: {
        hideNavBar: true,
        pageTitle: `${searchParams.get('other')}-${searchParams.get(`code`)}`,
        pageBackground: '#eee',
      },
    });
    checkAuthorize(
      (x) => setTokening(x),
      (y) => {
        console.log(`token检查完成，是否通过授权：${y}`);
        setAuthOK(y);
      },
      (z) => setTokenFail(z),
      model,
    );
  }, []);


  useEffect(() => {
    if (study?.code) {
      const { name, code, age, ageUnit, sex } = study;
      setPageNavBar({
        pagePath: location.pathname,
        navBar: {
          hideNavBar: true,
          pageTitle: `${name}-${age}${ageUnit.label}-${sex.label}-${code}`,
          pageBackground: '#eee',
        },
      });
    }
  }, [study])

  const handler = useRef<ToastHandler>();

  function load() {
    let times = 1;
    if (authOK) {
      handler.current = Toast.show({
        icon: 'loading',
        content: '正在载入',
        maskClickable: false,
        duration: 0,
      });
      fetch(
        `${urlPrefix}/api/study-handle/try-strat-diagnosis-when-get-detail/${searchParams.get(
          'id',
        )}`,
        getRequestInit(),
      )
        .then(async (rsp: Response) => {
          if (rsp.ok) {
            await rsp
              .json()
              .then(({ data, code, msg }: DetailResult<Study>) => {
                if (code === 0) {
                  if (data) {
                    setStudy(data!);

                    setEcgParams(data!.ecgParams);
                    setVerticalLines(data!.verticalLines);
                    setAutoAnalysisResult(data!.autoAnalysisResult || '');

                    if (data.wave) {
                      const x: EcgData = decodeWaveFromHexStr(
                        data.wave.zipWaveData,
                      );
                      setEcgData(x);
                      console.dir(x);
                    }
                  } // end if data
                  setLoadOK(msg);
                  handler.current?.close();
                  setActiveKey(data?.reportFileName ? 'previewReport' : 'wave');
                } else {
                  setLoadFails([...loadFails, msg]);
                  Toast.show({
                    icon: 'fail',
                    content: msg,
                    duration: 3000,
                  });
                }
              })
              .catch((reason) => {
                setLoadFails([...loadFails, reason]);
                Toast.show({
                  icon: 'fail',
                  content: `加载失败：${reason}`,
                });
              });
          }
        })
        .catch((reason: any) => {
          console.error(reason);
          setLoadFails([...loadFails, `加载部门：${reason}`]);
          Toast.show({
            icon: 'fail',
            content: `加载失败：${reason}`,
          });
        })
        .finally(() => {
          setLoadingTimes(--times);
        });
    } // end if authOK
  }
  useEffect(load, [searchParams.get('id'), authOK]);

  const handleAfteDiagnosisOrAudit = (data: AfterDiagnosisOrAudit) => {
    const { currentAction, current, next } = data!;
    if (next) {
      const ToNextStudyModalContent = ({
        next,
      }: {
        next: NextStudyAfterHandle;
      }) => {
        const {
          ecgParams,
          workingMode,
          id,
          name,
          age,
          ageUnit,
          code,
          autoAnalysisResult,
          impression,
          criticalLevel,
          criticalDescription,
          testResultStatus,
          lastLiving,
        } = next;
        const {
          standard: { value: stdv },
        } = lastLiving;
        const handleConfirm = () => {
          handler.close();
          navigate(`/study/diagnostic?id=${id}&code=${code}&name=${name}&other=${name + age + '-' + ageUnit.label + '-' + sex.label}`);
        };
        return (
          <div className="dialogPanner">
            <div className="infoRow">
              <div>
                <span>姓名：</span>
                <span>{name}</span>
              </div>
              <div>
                <span>性别：</span>
                <span>{sex.label}</span>
              </div>
            </div>

            <div className="infoRow">
              <div>
                <span>年龄：</span>
                <span>
                  {age}
                  {ageUnit.label}
                </span>
              </div>
              <div>
                <span>来源：</span>
                <span>{workingMode.label}</span>
              </div>
            </div>
            {ecgParams
              .filter(
                ({ param, value, configId, status }, index) =>
                  configId && status && status.value !== 'normal',
              )
              .map(({ param, value, status, rangeMax, rangeMin }, index) => (
                <div className="infoRow" key={index}>
                  <div style={{ width: '100%' }}>
                    <span className={styles.paramLabel}>{param.label}：</span>
                    <span
                      className={styles.paramValue}
                      style={{
                        backgroundColor: !status
                          ? '#FFFFFF'
                          : value <= rangeMin!
                            ? '#FFFF00'
                            : value > rangeMax!
                              ? '#FF0000'
                              : '#FFFFFF',
                      }}
                    >
                      {value}
                    </span>
                    <span className={styles.paramUnit}>{param.unit}</span>
                  </div>
                </div>
              ))}

            <div className="infoButton">
              <Button
                size="small"
                style={{
                  backgroundColor: '#f5f5f5',
                  color: '#666',
                  fontSize: '12px',
                  padding: '6px 12px',
                  border: 'none',
                }}
                onClick={() => handler.close()}
              >
                关闭
              </Button>

              <Button
                size="small"
                color="primary"
                style={{
                  fontSize: '12px',
                  padding: '6px 12px',
                }}
                onClick={handleConfirm}
              >
                {stdv === 'created' && '诊断'}
                {stdv === 'diagnosing' && '继续诊断'}
                {stdv === 'diagnosed' && '审核'}
                {stdv === 'auditing' && '继续审核'}
              </Button>
            </div>
          </div>
        );
      }; // end define ToNextStudyModalContent

      const handler: ModalShowHandler = Modal.show({
        title: `下一患者`,
        content: <ToNextStudyModalContent next={next} />,
        closeOnMaskClick: false,
      });
    } /*end if next*/ else {
      Toast.show({
        icon: 'success',
        content: '很好，你没有需要处理的申请单了！',
      });
    }
  }; // end  handleAfteDiagnosisOrAudit.

  function uploadReport() {
    if (!previewReportResult) {
      return;
    }
    handler.current = Toast.show({
      icon: 'loading',
      content: `正在上传...`,
      maskClickable: false,
      duration: 0,
    });
    let response: Promise<Response> = fetch(
      `${urlPrefix}/api/study-handle/diagnosis-or-audit-after-preview-report`,
      postRequestInit({ living: previewReportResult?.livingId }),
    );
    response
      .then((rsp: Response) => {
        console.log(rsp);
        if (rsp.ok) {
          rsp
            .json()
            .then(async (x: DetailResult<AfterDiagnosisOrAudit>) => {
              console.log(x);
              const { data, code, msg } = x;
              console.log('id =', data);
              if (code === 0) {
                handler.current?.close();
                handleAfteDiagnosisOrAudit(data!);
              } else {
                Toast.show({ icon: 'fail', content: msg });
              }
            })
            .catch((reason) => {
              Toast.show({
                icon: 'fail',
                content: `上传报告时发生错误：${reason}`,
              });
            });
        }
      })
      .catch((reason: any) => {
        console.error(reason);
        Toast.show({
          icon: 'fail',
          content: `上传报告时发生错误：${reason}`,
        });
      })
      .finally(() => { });
  } // end function

  if (tokening) {
    return (
      <div style={{ color: '#00b578' }}>
        <DotLoading color="currentColor" />
        <span>正在授权...</span>
      </div>
    );
  }
  // <span>正在载入,剩余{loadingTimes}个请求...</span>
  if (loadingTimes > 0) {
    return (
      <div style={{ color: '#00b578' }}>
        <DotLoading color="currentColor" />
      </div>
    );
  }

  const {
    name,
    age,
    ageUnit,
    device,
    sex,
    idCardNo,
    doctor,
    clinicalDepartment,
    diagnosisGroup,
    price,
    ecgType,
    fileNames,
    id,
    idCardType,
    pathPrefix,
    uid,
    workingMode,
    lastLiving,
    currentUserCanDoAudit,
    livingOfCurrentDoing,
    reportFileName,
  } = study!;

  //const fileUrl = `${'http://legacypdfviewer.billschen.com/web/viewer.html'}?file=${obsPrifix}/${encodeURIComponent(encodeURIComponent(`preview-pdf/${searchParams.get('uid')}/${searchParams.get('fileName')}`))}`;
  // 10c16e37-238d-458b-9074-f0879b5bc595
  // 0b429331-9d2c-40ab-aab7-d06d316a1360.pdf

  //const fileUrl = `${'http://legacypdfviewer.billschen.com/web/viewer.html'}?file=${obsPrifix}/${encodeURIComponent(encodeURIComponent(`preview-pdf/10c16e37-238d-458b-9074-f0879b5bc595/0b429331-9d2c-40ab-aab7-d06d316a1360.pdf`))}`;

  return (
    <Page>
      <Content>
        <div
          style={{
            height: '45px',
            position: 'fixed',
            left: 0,
            bottom: '0',
            width: '100%',
            zIndex: 99,
            backgroundColor: '#fff',
          }}
        >
          <Tabs
            activeKey={activeKey}
            onChange={(key) => {
              if (key === 'home') {
                navigate('/study/search');
                return;
              }
              setPreKey(activeKey);
              setActiveKey(key);
            }}
          >
            <Tabs.Tab
              title={
                <UnorderedListOutline style={{ width: '25px', height: 'auto' }} />
              }
              key="home"
            ></Tabs.Tab>
            <Tabs.Tab
              title={
                <img
                  src={activeKey == 'wave' ? bxyl : nBxyl}
                  style={{ width: '25px', height: 'auto' }}
                />
              }
              key="wave"
            ></Tabs.Tab>
            <Tabs.Tab
              title={
                <img
                  src={activeKey == 'report' ? zdsh : nZdsh}
                  style={{ width: '25px', height: 'auto' }}
                />
              }
              key="report"
            ></Tabs.Tab>
            <Tabs.Tab
              title={
                <img
                  src={activeKey == 'analysis' ? zdfx : nZdfx}
                  style={{ width: '25px', height: 'auto' }}
                />
              }
              key="analysis"
            ></Tabs.Tab>
            <Tabs.Tab
              disabled={!previewReportResult && !reportFileName}
              title={
                <img
                  src={activeKey == 'previewReport' ? bgyl : nBgyl}
                  style={{ width: '25px', height: 'auto' }}
                />
              }
              key="previewReport"
            ></Tabs.Tab>
          </Tabs>
          <div className=""></div>
        </div>

        <div
          style={{
            paddingBottom: 44,
          }}
        >
          <div
            style={{
              display: activeKey === 'previewReport' ? 'block' : 'none',
            }}
          >
            {((previewReportResult && previewReportResult.uid) ||
              reportFileName) && (
                <iframe
                  style={{ width: '100%', height: 'calc(100vh - 103px)' }}
                  src={`${'http://legacypdfviewer.billschen.com/web/viewer.html'}?file=${obsPrifix}/${encodeURIComponent(
                    encodeURIComponent(
                      `preview-pdf/${previewReportResult?.uid || uid}/${previewReportResult?.fileName || reportFileName
                      }`,
                    ),
                  )}`}
                ></iframe>
              )}
            {!reportFileName && (
              <div>
                <Button
                  block
                  type={'button'}
                  onClick={uploadReport}
                  color={'primary'}
                >
                  上传
                  {previewReportResult?.currentUserCanDoDiagnosis &&
                    '报告以供审核'}
                </Button>
              </div>
            )}
            {reportFileName && (
              <Button
                block
                type={'button'}
                onClick={uploadReport}
                color={'danger'}
              >
                召回报告
              </Button>
            )}
          </div>

          <div
            style={{
              display: activeKey === 'wave' ? 'block' : 'none',
            }}
          >
            <BackgroundGrid
              onPrintParaChange={setPrintParam}
              wave={study!.wave!}
              ecgData={ecgData!}
              setActiveKey={setActiveKey}
            />
          </div>

          <div
            style={{
              display: activeKey === 'analysis' ? 'block' : 'none',
            }}
          >
            <AnalysisOverlay
              wave={study!.wave!}
              ecgData={ecgData!}
              study={study!}
              ecgParams={ecgParams}
              setEcgParams={setEcgParams}
              verticalLines={verticalLines}
              setVerticalLines={setVerticalLines}
              autoAnalysisResult={autoAnalysisResult}
              setAutoAnalysisResult={setAutoAnalysisResult}
              visible={true}
              onSave={(s) => {
                console.log(s);
                setActiveKey('report');
              }}
              onClose={() => setActiveKey(preKey || 'report')}
            ></AnalysisOverlay>
          </div>

          <div
            style={{
              display: activeKey === 'report' ? 'block' : 'none',
            }}
          >
            <ReportEditor
              printParam={printParam}
              wave={study!.wave!}
              ecgData={ecgData!}
              study={study!}
              setActiveKey={setActiveKey}
              setPreKey={setPreKey}
              verticalLines={verticalLines}
              ecgParams={ecgParams}
              setEcgParams={setEcgParams}
              setVerticalLines={setVerticalLines}
              autoAnalysisResult={autoAnalysisResult}
              setAutoAnalysisResult={setAutoAnalysisResult}
              handleAfteDiagnosisOrAudit={handleAfteDiagnosisOrAudit}
              afterPreviewReport={(e: PreviewReprot) => {
                console.log(`afterPreviewReport happen =`, e);
                setPreviewReportResult(e);
                setActiveKey('previewReport');
              }}
            ></ReportEditor>
          </div>
        </div>
      </Content>
    </Page>
  );
};
